/*
 * Copyright (c) 2009-2013 EvTech Project
 * All rights reserved.
 * 
 * This file is part of Game packet.
 *
 * Game packet is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version.
 *
 * Game packet is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Game packet.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package fi.honkalampisaatio.game.utilities;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;

import javax.sound.sampled.Clip;

import org.ldtwo.jgoogle_tts.Worker;

import fi.honkalampisaatio.sound.SoundPlayer;

public class TextToSpeech {
	public static TextToSpeech INSTANCE;
	private String ttsProgramPath;
	private String defaultSaveFile;
	
	public static TextToSpeech getInstance() {
		if(INSTANCE==null) {
			INSTANCE = new TextToSpeech();
		}
		return INSTANCE;
	}
	
	public TextToSpeech() {
		this.ttsProgramPath = "C:/Program Files/eSpeak/command_line/espeak.exe";
		this.defaultSaveFile = "C:/WINDOWS/Temp/temp.wav";
	}
	
	public void setPaths(String ttsProgramPath, String defaultSaveFile) {
		this.ttsProgramPath = ttsProgramPath;
		this.defaultSaveFile = defaultSaveFile;
	}
	
	public void copyFile(File sourceFile, File destFile) throws IOException {
	    if(!destFile.exists()) {
	        destFile.createNewFile();
	    }

	    FileChannel source = null;
	    FileChannel destination = null;

	    try {
	        source = new FileInputStream(sourceFile).getChannel();
	        destination = new FileOutputStream(destFile).getChannel();
	        destination.transferFrom(source, 0, source.size());
	    }
	    finally {
	        if(source != null) {
	            source.close();
	        }
	        if(destination != null) {
	            destination.close();
	        }
	    }
	}
	
    protected String format(String s){
        s=s.toLowerCase().replace("jgoogle", " chay google ")//
                .replace(" tts", " text to speech ").replace("+", " ");
        String ret="";
        for(char ch:s.toCharArray()){
            if(Character.isLetterOrDigit(ch))
                ret+=""+ch;
            else ret+=" ";
        }
        while(ret.contains("  "))ret=ret.replace("  ", " ");
        return ret.trim().replace(" ", "+");
    }
    
	public SoundPlayer getSoundPlayer(String sentence)
	{
		if(sentence==null || sentence.isEmpty())
		{
			return null;
		}
		System.out.println("TTS: " + sentence);
		SoundPlayer player = new SoundPlayer();
		if(!player.setSoundFile("./ttsVoices/" + sentence + ".mp3"))
		{
			File folder = new File("./ttsVoices/");
			if(!folder.exists()) {
				try {
					System.out.println("creating folder: ./ttsVoices/");
					folder.mkdirs();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			Worker worker = new Worker("fi");
			File mp3File = worker.getAndPlay("translate.google.com", format(sentence), false);
			if(mp3File != null)
			{
				System.out.println("created mp3");
				try {
					copyFile(mp3File, new File("./ttsVoices/" + sentence + ".mp3"));
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			player.setSoundFile("./ttsVoices/" + sentence + ".mp3");
		}

		if(!player.isLoaded())
		{
			System.out.println("trying wav");
			//load wav
			if(!player.setSoundFile("./ttsVoices/" + sentence + ".wav"))
			{
				System.out.println("creating wav");
				createWav(sentence, "./ttsVoices/" + sentence + ".wav");
				player.setSoundFile("./ttsVoices/" + sentence + ".wav");
			}
		}
		
		if(!player.isLoaded())
		{
			System.out.println("TTS failed");
			player=null;
		}
		return player;
	}

	public Clip getSpeechClip(String sentence, String filepath) {
		Clip speech = null;
		if(filepath == null)
		{
			createWav(sentence, defaultSaveFile);
			speech = MediaLoader.createSoundClip(defaultSaveFile);
		}
		else if(new File(filepath).exists())
		{
			speech = MediaLoader.createSoundClip(filepath);
		}
		else
		{
			createWav(sentence, filepath);
			speech = MediaLoader.createSoundClip(filepath);
		}
		if(speech==null)
		{
	        System.err.println("Couldn't create speech clip: " + filepath);
		}
		return speech;
	}
	
	private void createWav(String sentence, String filepath) {
        try {
        	File file = new File(filepath);
	        File dir = file.getParentFile();
	        if(dir!=null && !dir.exists()) {
	        	dir.mkdirs();
	        	dir.setWritable(true, false);
	        }
            String[] commands = {"\""+this.ttsProgramPath+"\"",
            		"-vfi",
            		"-w"+"\""+filepath+"\"",
            		"\""+sentence+"\""};
			Process p = Runtime.getRuntime().exec(commands, null, new File(System.getProperty("user.dir")));
			
			BufferedReader br = new BufferedReader(new
							InputStreamReader(p.getInputStream()));
			
			String line;
			while((line = br.readLine()) != null) {
		        System.out.println(line);
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

}
